package com.jinxin.platform.cdinfogo.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jinxin.platform.base.common.pojo.JsonResult;
import com.jinxin.platform.cdinfogo.mapper.CdinfogoLedModuleMapper;
import com.jinxin.platform.cdinfogo.mapper.CdinfogoLedProgramMapper;
import com.jinxin.platform.cdinfogo.pojo.domain.CdinfogoLedModule;
import com.jinxin.platform.cdinfogo.pojo.domain.CdinfogoLedProgram;
import com.jinxin.platform.cdinfogo.pojo.vo.Constant;
import com.jinxin.platform.cdinfogo.rpc.CdInfoGoRpcService;
import com.jinxin.platform.cdinfogo.service.IZsLedService;
import com.jinxin.platform.cdinfogo.utils.DateUtil;
import com.jinxin.platform.cdinfogo.utils.IdWorker;
import com.jinxin.platform.cdinfogo.utils.LEDSender2010;
import com.jinxin.platform.cdinfogo.utils.NumConvertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * All rights Reserved, Designed By www.beonelot.com
 *
 * @version: V1.0
 * @Copyright: www.beonelot.com Inc. All rights reserved.
 * @Description：
 * @Date: 2021-11-22
 * @Author: Lingnan
 **/
@Service
@Slf4j
public class ZsLedServiceImpl implements IZsLedService {
    @Autowired
    private CdinfogoLedProgramMapper ledProgramMapper;
    @Autowired
    private CdinfogoLedModuleMapper ledModuleMapper;
    @Autowired
    private CdInfoGoRpcService cdInfoGoRpcService;
    @Resource
    private IdWorker idWorker;
    @Autowired
    private PlatformTransactionManager transactionManager;

    @Override
    public JsonResult queryProgramByMac(String mac) {
        if(StringUtils.isEmpty(mac)){
            return JsonResult.error("mac不存在,参数错误");
        }
        HashMap param = new HashMap();
        param.put("mac",mac);
        List<CdinfogoLedProgram> list = ledProgramMapper.list(param);
        if(list.size() == 0){
            return JsonResult.error("节目不存在");
        }
        list.forEach(program -> {
            HashMap param2 = new HashMap();
            param2.put("mac",mac);
            param2.put("programId",program.getId());
            List<CdinfogoLedModule> moduleList = ledModuleMapper.list(param2);
            program.setModuleList(moduleList);
        });
        return JsonResult.ok("success",list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult saveOrUpdateProgram(List<CdinfogoLedProgram> programList) {
        int result = 0;
        for(int i = 0; i < programList.size(); i++){
            CdinfogoLedProgram program = programList.get(i);
            String programId = program.getId();
            List<CdinfogoLedModule> moduleList = program.getModuleList();
            CdinfogoLedProgram ledProgram = ledProgramMapper.selectByKey(programId);
            if(ledProgram == null){
                program.setXh((i+1));
                int n = ledProgramMapper.insert(program);
                if(n > 0){
                    List<CdinfogoLedModule> newModuleList = new ArrayList<>();
                    for(int j=0;j<moduleList.size();j++){
                        CdinfogoLedModule module = moduleList.get(j);
                        module.setXh((j+1));
                        module.setProgramId(programId);
                        newModuleList.add(module);
                    }
                    if(newModuleList.size() == 0){
                        result++;
                    }else {
                        int count = ledModuleMapper.insertBatch(newModuleList);
                        if(count > 0){
                            result++;
                        }
                    }
                }
            }else {
                int count = ledProgramMapper.updateByKey(program);
                if(count > 0){
                    for (int j = 0; j < moduleList.size(); j++) {
                        CdinfogoLedModule module = moduleList.get(j);
                        module.setXh((j+1));
                        CdinfogoLedModule ledModule = ledModuleMapper.selectByKey(module.getId());
                        int r = 0;
                        if(ledModule == null){
                            r += ledModuleMapper.insert(module);
                        }else {
                            r += ledModuleMapper.updateByKey(module);
                        }
                        if(r > 0){
                            result++;
                        }
                    }
                }
            }
        }
        if(result == 0){
            return JsonResult.error("保存失败或参数错误");
        }
        return JsonResult.ok("节目保存或更新成功",null);
    }

    private int saveProgram(CdinfogoLedProgram program,List<CdinfogoLedModule> moduleList){
        int result = 0;
        String programId = program.getId();
        String mac = program.getMac();
        CdinfogoLedProgram ledProgram = ledProgramMapper.selectByKey(programId);
        if(ledProgram == null){
            Integer maxXh = ledProgramMapper.selectMaxXhByMac(mac);
            int xh = maxXh == null ? 1 : maxXh + 1;
            program.setXh(xh);
            int n = ledProgramMapper.insert(program);
            if(n > 0){
                List<CdinfogoLedModule> newModuleList = new ArrayList<>();
                for(int j=0;j<moduleList.size();j++){
                    CdinfogoLedModule module = moduleList.get(j);
                    module.setXh((j+1));
                    module.setProgramId(programId);
                    newModuleList.add(module);
                }
                if(newModuleList.size() == 0){
                    result++;
                }else {
                    int count = ledModuleMapper.insertBatch(newModuleList);
                    if(count > 0){
                        result++;
                    }
                }
            }
        }else {
            int count = ledProgramMapper.updateByKey(program);
            if(count > 0){
                for (int j = 0; j < moduleList.size(); j++) {
                    CdinfogoLedModule module = moduleList.get(j);
                    module.setXh((j+1));
                    CdinfogoLedModule ledModule = ledModuleMapper.selectByKey(module.getId());
                    int r = 0;
                    if(ledModule == null){
                        r += ledModuleMapper.insert(module);
                    }else {
                        r += ledModuleMapper.updateByKey(module);
                    }
                    if(r > 0){
                        result++;
                    }
                }
            }
        }
        return result;
    }

    @Override
    public JsonResult saveAsMode(CdinfogoLedProgram program) {
        if(program == null){
            return JsonResult.error("参数错误,生成模式失败");
        }
        List<CdinfogoLedModule> moduleList = program.getModuleList();
        if(moduleList.size() == 0){
            return JsonResult.error("组件缺失,生成模式失败");
        }
        if(saveProgram(program, moduleList) <= 0){
            return JsonResult.error("节目保存失败");
        }
        String paramData = generateParamData(moduleList);
        String mac = program.getMac();
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);//新发起一个事务
        TransactionStatus transaction = transactionManager.getTransaction(def);
        JsonResult jsonResult2 = null;
        try {
            String account = program.getAccount();
            String programId = program.getId();
            JsonResult jsonResult = cdInfoGoRpcService.saveProgram("", programId, paramData, mac);
            if(!jsonResult.getSuccess()){
                transactionManager.rollback(transaction);
                return JsonResult.error(jsonResult.getMsg());
            }
            JSONObject jsObj = new JSONObject();
            jsObj.put("cmdId", Constant.CMD_SHOW_PROGRAM);
            JSONObject paramObj = new JSONObject();
            paramObj.put("p1",Constant.DEFAULT_LED_PORT);
            paramObj.put("p2",programId);
            jsObj.put("cmdPapam", JSON.toJSON(paramObj));
            jsObj.put("deviceMac", mac);
            String deviceName = program.getDeviceName();
            jsObj.put("deviceName", deviceName);
            String productCode = program.getProductCode();
            jsObj.put("productCode", productCode);
            JSONArray jsonArray = new JSONArray();
            jsonArray.add(jsObj);
            String msmls = jsonArray.toJSONString();
            jsonResult2 = cdInfoGoRpcService.addMode(account, msmls, program.getName(),program);
            if(jsonResult2.getSuccess()){
                transactionManager.commit(transaction);
            }else {
                transactionManager.rollback(transaction);
            }
        }catch (Exception e){
            log.error(e.toString());
            transactionManager.rollback(transaction);
        }
        return jsonResult2;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult sendToScreen(CdinfogoLedProgram program) {
        if(program == null){
            return JsonResult.error("参数错误,下发节目失败");
        }
        List<CdinfogoLedModule> moduleList = program.getModuleList();
        if(moduleList.size() == 0){
            return JsonResult.error("组件缺失,下发节目失败");
        }
        if(StringUtils.isEmpty(saveProgram(program, moduleList))){
            return JsonResult.error("节目保存失败");
        }
        String hexStr = generateParamData(moduleList);
        log.info("生成的节目数据: " + hexStr);
        return cdInfoGoRpcService.sendToScreen("",hexStr, program.getMac());
    }

    private String generateParamData(List<CdinfogoLedModule> moduleList){
        LEDSender2010 ledsender = new LEDSender2010();
        String[] formats_YMDHNS={"#y", "年", "#m", "月", "#d", "日", " ", "#h", ":", "#n", ":", "#s"};
        String[] formats_WEEK={"星期", "#w"};
        String[] formats_YMD={"#y", "年", "#m", "月", "#d", "日"};
        String[] formats_HNS={"#h", ":", "#n", ":", "#s"};
        for (int i = 0; i < moduleList.size(); i++) {
            if(i == 0){
                //生成节目数据
                ledsender.MakeRoot(LEDSender2010.ROOT_DOWNLOAD, LEDSender2010.COLOR_TYPE_DOUBLE);
                //ledsender.MakeRoot(LEDSender2010.ROOT_PLAY, LEDSender2010.COLOR_TYPE_THREE);
                //ledsender.MakeRoot(LEDSender2010.ROOT_PLAY, LEDSender2010.COLOR_TYPE_FULL);
                ledsender.AddChapter(1, 1000);
                ledsender.AddRegion(0, 0, 256*100, 64*100);
                ledsender.AddLeaf(1, 2000);
            }
            CdinfogoLedModule module = moduleList.get(i);
            if(module == null){continue;}
            Integer leftMargin = module.getLeftMargin();
            Integer topMargin = module.getTopMargin();
            Integer width = module.getWidth();
            Integer height = module.getHeight();
            Integer fontSize = module.getFontSize();
            String fontColorStr = module.getFontColor();
            String content = module.getContent();
            Integer inmethod = module.getInmethod();
            Integer outmethod = module.getOutmethod();
            Integer alignment = module.getAlignment();
            Integer stopmethod = module.getStopmethod();
            String fontFamily = module.getFontFamily();
            if(inmethod == null){
                inmethod = 0; //默认随机
            }
            if(outmethod == null){
                outmethod = 0; //默认随机
            }
            if(stopmethod == null){
                stopmethod = 0; //默认静态显示
            }
            if(StringUtils.isEmpty(fontFamily)){
                fontFamily = "宋体";
            }
            Color fc = Color.YELLOW;
            if(!StringUtils.isEmpty(fontColorStr)){
                String[] rgb = fontColorStr.replaceAll("\\(|\\)","").split(",");
                if(rgb.length == 3){
                    int r = Integer.parseInt(rgb[0]);
                    int g = Integer.parseInt(rgb[1]);
                    int b = Integer.parseInt(rgb[2]);
                    fc = new Color(r,g,b);
                }
            }
            switch (module.getModuleType()){ // 类型1数字时间2文本输入3图片显示4倒(正)计时5模拟时钟
                case 1:
                    Integer timeFormatter = module.getTimeFormatter();
                    String[] formats;
                    if(timeFormatter == null){
                        formats = formats_YMDHNS;
                    }else {
                        switch (timeFormatter){
                            case 1:formats = formats_YMDHNS;break;
                            case 2:formats = formats_WEEK;break;
                            case 3:formats = formats_YMD;break;
                            case 4:formats = formats_HNS;break;
                            default: formats = formats_YMDHNS;break;
                        }
                    }
                    ledsender.AddDateTime(leftMargin, topMargin, width, height, formats, formats.length, fontFamily, fontSize, Color.BLACK, fc, 0);
                    break;
                case 2:
                    //ledsender.AddText(leftMargin, topMargin, width, height, content, "宋体", fontSize, Color.BLACK, fc, 0, alignment, false, inmethod, 0, 2, 0, 0, 0, 0);
                    ledsender.AddTextEx(leftMargin, topMargin, width, height, content, alignment,0,fontFamily, fontSize, Color.BLACK, fc, 0, inmethod, 0, outmethod, 0, stopmethod, 0, 0);
                    break;
                case 3:
                    ledsender.AddPicture(leftMargin, topMargin, width, height,content, inmethod, 0, outmethod, 0, stopmethod, 0, 0);
                    break;
                case 4:
                    Integer countType = module.getCountType();
                    Integer countFormatType = module.getCountFormatType();
                    if(countType != null && countFormatType != null){
                        int year=0, month=0, day=0, hour=0, minute=0, second=0;
                        if(DateUtil.isLegalDate(content.length(),content,"HH:mm:ss")){
                            String[] dateArr = content.split(":");
                            hour = Integer.parseInt(dateArr[0]);
                            minute = Integer.parseInt(dateArr[1]);
                            second = Integer.parseInt(dateArr[2]);
                        }else if(DateUtil.isLegalDate(content.length(),content,"yyyy-MM-dd HH:mm:ss")){
                            String[] timeStr = content.split(" ");
                            String[] dateArr = timeStr[0].split("-");
                            String[] timeArr = timeStr[1].split(":");
                            year = Integer.parseInt(dateArr[0]);
                            month = Integer.parseInt(dateArr[1]);
                            day = Integer.parseInt(dateArr[2]);
                            hour = Integer.parseInt(timeArr[0]);
                            minute = Integer.parseInt(timeArr[1]);
                            second = Integer.parseInt(timeArr[2]);
                        }
                        ledsender.AddCounter(leftMargin, topMargin, width, height, year, month, day, hour, minute, second, countType, countFormatType, fontFamily, fontSize, Color.BLACK, fc, 0);
                    }
                    break;
                case 5: //模拟时钟
                    ledsender.AddClock(leftMargin, topMargin, width, height,Color.BLACK, Color.YELLOW, 0, Color.YELLOW, 5, 2, 0, Color.YELLOW, 4, Color.YELLOW, 4, Color.YELLOW, 1);
                    break;
            }
        }
        // 计算数据长度(前低后高)
        byte[] bytes =  ledsender.data_stream;
        String size1 = Integer.toHexString(bytes[5] & 0xFF);
        String size2 = Integer.toHexString(bytes[4] & 0xFF);
        String sizeHex = (size1.length() < 2 ? "0"+size1 : size1) + (size2.length() < 2 ? "0"+size2 : size2);
        int length = NumConvertUtil.hexStringToInt(sizeHex);
        return NumConvertUtil.bytesToHex(bytes, length);
    }

    @Override
    public JsonResult removeProgramById(String id) {
        if(StringUtils.isEmpty(id)){
            return JsonResult.error("节目ID为空");
        }
        CdinfogoLedProgram program = ledProgramMapper.selectByKey(id);
        if(program == null){
            return JsonResult.error("节目不存在");
        }
        int count = ledProgramMapper.deleteByKey(id);
        return count > 0 ? JsonResult.ok("删除成功",null) : JsonResult.error("删除失败");
    }

    @Override
    public JsonResult removeModuleById(String id) {
        if(StringUtils.isEmpty(id)){
            return JsonResult.error("组件ID为空");
        }
        CdinfogoLedModule module = ledModuleMapper.selectByKey(id);
        if(module == null){
            return JsonResult.error("组件不存在");
        }
        int count = ledModuleMapper.deleteByKey(id);
        return count > 0 ? JsonResult.ok("删除成功",null) : JsonResult.error("删除失败");
    }
}
